home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <signal.h>
- #include <math.h>
- #include "geom.h"
- #include "polylistP.h"
- #include "3d.h"
- #include "ooglutil.h"
- #include "hinge.h"
- #include "hui.h"
-
- /*
- pl is the polyhedron we're dealing with.
-
- int pl->n_verts: total number of vertices in the polyhedron
- HPoint3 pl->vl[]: array containing vertices
- int pl->n_polys: total number of faces in the polyhedron
- Poly pl->p[]: array containing the faces
- int pl->p[i].n_vertices: number of vertices in i-th face
- HPoint3 pl->p[i].v[j]->pt: j-th vertex of i-th face
- */
- PolyList *pl;
-
-
- Transform *TT[MAXTHINGS];
-
- float epsilon = .005;
-
- /* pipes to and from geomview */
- FILE *togv, *fromgv;
-
- char hingedatastring[] =
- #include "hingedata.h"
- ;
-
- /* the space we're in */
- int space = HYPERBOLIC;
-
- /* whether a rotation axis is currently defined */
- int haveaxis = 0;
-
- /* the angle to rotate through */
- float angle = 90;
-
- /* increments by which to rotate */
- float hingeincr = 5.0;
-
- /* whether to kill geomview when we exit or die */
- int killgv = 0;
-
- Point currentedge[2];
- Point base = {0, 0, 0, 1};
- Point tip = {0, 0, 1, 1};
- Point axis = {0, 0, 1, 1};
- Transform BaseT;
-
- int mainpos[2];
- int helppos[2];
- int infopos[2];
- int filepos[2];
-
- char *file = NULL;
-
- static void space_alignZ(Point *a, Point *b, Transform T);
-
- #define NEXTARG ++argv; --argc
-
- usage()
- {
- fprintf(stderr, "hinge [OPTIONS] [FILE]\n\
- OPTIONS:\n\
- -space {euclidean|hyperbolic}\n\
- -angle a (set angle initially to a degrees)\n\
- -incr a (hinge through increments of a degrees)\n\
- -killgv (kill geomview upon exit)\n\
- -mpos x y (position of main panel)\n\
- -hpos x y (position of help panel)\n\
- -ipos x y (position of info panel)\n\
- -fpos x y (position of file panel)\n");
- exit(-1);
- }
-
- void die(int sig, int code, struct sigcontext *sc)
- {
- QuitProc(NULL,0);
- }
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- signal(SIGHUP, die);
- signal(SIGINT, die);
- signal(SIGQUIT, die);
- signal(SIGILL, die);
- signal(SIGTRAP, die);
- signal(SIGABRT, die);
- signal(SIGBUS, die);
- signal(SIGSEGV, die);
- signal(SIGPIPE, die);
- signal(SIGTERM, die);
-
- NEXTARG;
-
- while (argc) {
- if (!strcmp(argv[0],"-killgv")) {
- killgv = 1;
- } else if (!strcmp(argv[0],"-space")) {
- NEXTARG;
- if (!argc) usage();
- if (!strcmp(argv[0],"hyperbolic")) {
- space = HYPERBOLIC;
- } else if (!strcmp(argv[0],"spherical")) {
- space = SPHERICAL;
- } else {;
- space = EUCLIDEAN;
- }
- } else if (!strcmp(argv[0], "-incr")) {
- NEXTARG;
- if (!argc) usage();
- hingeincr = atof(argv[0]);
- } else if (!strcmp(argv[0], "-angle")) {
- NEXTARG;
- if (!argc) usage();
- angle = atof(argv[0]);
- } else if (!strcmp(argv[0], "-mpos")) {
- NEXTARG;
- if (argc<2) usage();
- mainplacement = FL_PLACE_POSITION;
- mainpos[0] = atoi(argv[0]);
- mainpos[1] = atoi(argv[1]);
- NEXTARG;
- } else if (!strcmp(argv[0], "-fpos")) {
- NEXTARG;
- if (argc<2) usage();
- fileplacement = FL_PLACE_POSITION;
- filepos[0] = atoi(argv[0]);
- filepos[1] = atoi(argv[1]);
- NEXTARG;
- } else if (!strcmp(argv[0], "-ipos")) {
- NEXTARG;
- if (argc<2) usage();
- infoplacement = FL_PLACE_POSITION;
- infopos[0] = atoi(argv[0]);
- infopos[1] = atoi(argv[1]);
- NEXTARG;
- } else if (!strcmp(argv[0], "-hpos")) {
- NEXTARG;
- if (argc<2) usage();
- helpplacement = FL_PLACE_POSITION;
- helppos[0] = atoi(argv[0]);
- helppos[1] = atoi(argv[1]);
- NEXTARG;
- } else {
- file = argv[0];
- if (argc>1) {
- fprintf(stderr, "hinge: ignoring arguments after %s\n", file);
- break;
- }
- }
-
- NEXTARG;
- }
-
- hui_init();
- Initialize();
- hui_main_loop();
- }
-
- Initialize()
- {
- int i;
-
- LangInit();
-
- for (i=0; i<MAXTHINGS; ++i) TT[i] = NULL;
- togv = stdout;
- fromgv = stdin;
- TmCopy(TM_IDENTITY, BaseT);
- NewInst(0.0);
- fprintf(togv, "(progn\n\
- (normalization allgeoms none)\n\
- (lines-closer allcams 1)\n\
- (merge-baseap appearance { +edge })\n\
- )\n");
- HingeSpace(space);
-
-
- if (file == NULL) {
- switch (space) {
- case HYPERBOLIC:
- file = "HingeDodec";
- break;
- default:
- case EUCLIDEAN:
- file = "HingeCube";
- break;
- }
- }
-
- if (file != NULL) {
- HingeLoad(file);
- }
-
-
- {
- Geom *g = NULL;
- FILE *fp = fopen("hingedata", "r");
- if (fp == NULL)
- fp = fstropen(hingedatastring, sizeof(hingedatastring), "r");
- if (fp == NULL) {
- OOGLError(0,"can't find the file \"hingedata\"; it must be\n\
- in the current directory. This will be fixed soon. [mbp]");
- exit(-1);
- }
- if (fp != NULL) {
- g = GeomFLoad(fp, "hinge data");
- fclose(fp);
- }
- if (g != NULL) {
- DefinePick(g);
- } else {
- OOGLError(1,"can't read hinge data\n");
- exit(-1);
- }
- }
-
- fprintf(togv, "(interest (pick world))\n");
- fflush(togv);
- }
-
- int WhichFace(HPoint3 *p, Transform T, PolyList *pl)
- {
- int i;
-
- for (i=0; i<pl->n_polys; ++i) {
- if (CoPlanar(p, T, &(pl->p[i]))) return i;
- }
- return -1;
- }
-
- /*-----------------------------------------------------------------------
- * Function: CoPlanar
- * Description: test whether a point is coplanar with the image
- * of a polygon
- * Args: *p: the point
- * T: transform to apply to poly before test
- * *poly: the polygon
- * Returns: 1 if yes, 0 if no
- * Author: mbp
- * Date: Thu Oct 1 10:06:39 1992
- * Notes: Uses global variable "epsilon" for test.
- * The plane of the polygon is assumed to be
- * that determined by its first 3 vertices. This
- * assumes that those vertices are not collinear.
- * If they are collinear, this test may falsely
- * return 1.
- *
- */
- int CoPlanar(HPoint3 *p, Transform T, Poly *poly)
- {
- register HPoint3 v0;
- register HPoint3 v1;
- register HPoint3 v2;
- float det;
- int ans;
-
- HPt3Transform(T, &(poly->v[0]->pt), &v0);
- HPt3Transform(T, &(poly->v[1]->pt), &v1);
- HPt3Transform(T, &(poly->v[2]->pt), &v2);
-
-
- /* the following is the determinant of the 4x4 matrix
- whose 1st 3 rows are the homog coords of the polygon's
- 1st 3 vertices, and whose last row is the homog coords
- of p */
- det =
- p->x * ( v2.w*v1.y*v0.z
- - v1.w*v2.y*v0.z
- - v2.w*v0.y*v1.z
- + v0.w*v2.y*v1.z
- + v1.w*v0.y*v2.z
- - v0.w*v1.y*v2.z ) +
- p->y * (- v2.w*v1.x*v0.z
- + v1.w*v2.x*v0.z
- + v2.w*v0.x*v1.z
- - v0.w*v2.x*v1.z
- - v1.w*v0.x*v2.z
- + v0.w*v1.x*v2.z ) +
- p->z * ( v2.w*v1.x*v0.y
- - v1.w*v2.x*v0.y
- - v2.w*v0.x*v1.y
- + v0.w*v2.x*v1.y
- + v1.w*v0.x*v2.y
- - v0.w*v1.x*v2.y ) +
- p->w * (- v2.x*v1.y*v0.z
- + v1.x*v2.y*v0.z
- + v2.x*v0.y*v1.z
- - v0.x*v2.y*v1.z
- - v1.x*v0.y*v2.z
- + v0.x*v1.y*v2.z );
-
- ans = fabs(det) <= epsilon;
- return ans;
- }
-
-
- float HPt3EucDistance( HPoint3 *a, HPoint3 *b )
- {
- Point3 aa, ab;
- float dist;
-
- HPt3ToPt3(a, &aa);
- HPt3ToPt3(b, &ab);
- dist = Pt3Distance( &aa, &ab );
- return dist;
- }
-
- int pt4equal(HPoint3 *a, HPoint3 *b)
- {
- float dist;
- int ans;
-
- dist = HPt3EucDistance( a, b );
- ans = dist <= epsilon;
- return ans;
- }
-
- #if 0 /* commented out until spherical mode can be added; don't need
- this now */
- float space_distance(HPoint3 *a, HPoint3 *b)
- {
- float dist;
- Point3 aa, bb;
-
- switch (space) {
- default:
- case EUCLIDEAN:
- dist = HPt3EucDistance( a, b );
- return dist;
- break;
- case HYPERBOLIC:
- dist = HPt3HypDistance( a, b );
- return dist;
- break;
- }
- }
-
- float HPt3HypDistance( HPoint3 *a, HPoint3 *b )
- {
- float ab, aa, bb, dist, p, s;
- extern double acosh(double);
-
- ab = MinkDot(a,b);
- aa = MinkDot(a,a);
- bb = MinkDot(b,b);
- p = ab*ab / (aa * bb);
- if (p < 1) return 0;
- s = sqrt(p);
- dist = 2 * acosh( (double)s );
- return dist;
- }
-
- float MinkDot( HPoint3 *a, HPoint3 *b )
- {
- return a->x*b->x + a->y*b->y + a->z*b->z - a->w*b->w;
- }
- #endif
-
-
- /*-----------------------------------------------------------------------
- * Function: PolyContainsEdge
- * Description: test whether the image of a polygon contain an edge
- * Args: e[]: array of two points --- the endpoints of the edge
- * T: transform to apply to the polygon
- * *poly: the polygon
- * Returns: -1, 0, or 1 (see below)
- * Author: mbp
- * Date: Thu Oct 1 12:28:36 1992
- * Notes: returns 1 if the polygon contains the edge with the vertices
- * in the same order, -1 if opposite order, 0 if polygon doesn't
- * contain the edge at all.
- */
- int PolyContainsEdge(Point e[], Transform T, Poly *poly)
- {
- int i,ans;
- HPoint3 v;
-
- ans = 0;
- for (i=0; i<poly->n_vertices; ++i) {
- HPt3Transform(T, &(poly->v[i]->pt), &v);
- if (pt4equal(&e[0], &v)) {
- HPt3Transform(T, &(poly->v[(i+1)%poly->n_vertices]->pt), &v);
- if (pt4equal(&e[1], &v)) {
- ans = 1;
- goto done;
- }
- HPt3Transform(T, &(poly->v[(i-1+poly->n_vertices)%poly->n_vertices]->pt), &v);
- if (pt4equal(&e[1], &v)) {
- ans = -1;
- goto done;
- }
- }
- }
- done:
- return ans;
- }
-
- /* for debugging, just to make sure we understand what we have... */
- void WritePolyListInfo(PolyList *pl)
- {
- int i,j;
- FILE *fp = fopen("hinge.out", "w");
-
- fprintf(fp, "%1d vertices\n\n", pl->n_verts);
- for (i=0; i<pl->n_verts; ++i) {
- fprintf(fp, "vert[%2d] = (%6f, %6f, %6f, %6f)\n",
- i,
- pl->vl[i].pt.x,
- pl->vl[i].pt.y,
- pl->vl[i].pt.z,
- pl->vl[i].pt.w);
- }
- fprintf(fp, "\n");
- fprintf(fp, "%1d faces\n\n", pl->n_polys);
- for (i=0; i<pl->n_polys; ++i) {
- fprintf(fp, "face %1d has %1d vertices:\n", i, pl->p[i].n_vertices);
- for (j=0; j<pl->p[i].n_vertices; ++j) {
- fprintf(fp, "\t(%6f, %6f, %6f, %6f)\n",
- pl->p[i].v[j]->pt.x,
- pl->p[i].v[j]->pt.y,
- pl->p[i].v[j]->pt.z,
- pl->p[i].v[j]->pt.w);
- }
- }
- fclose(fp);
- }
-
- int
- HingeLoad(char *file)
- {
- FILE *f;
- Geom *g;
-
- if (strlen(file)<=0) return 0;
-
- /*
- The following kludge uses geomview to get the data; we tell
- geomview to load it, then dump it back to us, then delete it.
- */
- fprintf(togv,"(progn\n\
- (geometry thing { < %s })\n\
- (echo \"{\")\n\
- (write geometry - thing self)\n\
- (echo \"}\")\n\
- (delete thing)\n\
- )\n", file);
- fflush(togv);
-
- /*
- * We now read the object we just told geomview to give us.
- */
- g = GeomFLoad(fromgv, "Hinge: pipe from geomview");
-
- if (g == NULL) {
- fprintf(stderr, "Hinge: error reading geometry from file %s\n", file);
- } else {
- char buf[80];
- DefineThing(g);
- sprintf(buf,"%s",file);
- hui_message(buf);
- haveaxis = 0;
- ShowAxis();
- }
- pl = (PolyList *)g;
- return g != NULL;
- }
-
-
- int
- NewInst(float ang)
- {
- int n = NewTTindex();
- fprintf(togv,
- "(progn (read geometry { define T%1d { LIST } } )\n\
- (geometry \"geom%1d\" { INST tlist { LIST { :T%1d } } geom :thing } ) )\n",
- n, n, n);
- fflush(togv);
- Inst(n, 0.0);
- return n;
- }
-
- void
- ComputeTransform(Transform T, Transform BaseT, float ang)
- {
- if (ang == 0) {
- TmCopy(BaseT, T);
- } else {
- Rotation(T, ¤tedge[0], ¤tedge[1], RADIANS(ang));
- TmConcat(BaseT, T, T);
- }
- }
-
- int
- NewTTindex()
- {
- int i;
- for (i=0; i<MAXTHINGS && TT[i]!=NULL; ++i);
- if (i==MAXTHINGS) return -1;
- /* TT[i] = (TmCoord *(*)[4])malloc(sizeof(Transform)); */
- TT[i] = (void*)malloc(sizeof(Transform));
- TmCopy(TM_IDENTITY, TT[i]);
- return i;
- }
-
- void
- DefineAxis(Point *a, Point *b)
- {
- haveaxis = 1;
- currentedge[0] = *a;
- currentedge[1] = *b;
- base = *a;
- tip = *b;
- HPt3Sub(b, a, &axis);
- }
-
- void
- Rotation(Transform T, Point *a, Point *b, float angle)
- {
- Transform A;
-
- space_alignZ(a, b, A);
- TmInvert(A,A);
- TmRotateZ(T, angle);
- TmConjugate(T, A, T);
- }
-
- void
- DefineThing(Geom *g)
- {
- fprintf(togv,"(read geometry { define thing {\n");
- GeomFSave(g, togv, "hinge output pipe (define thing...)");
- fprintf(togv, "} } )\n");
- fflush(togv);
- }
-
- void
- DefinePick(Geom *g)
- {
-
- fprintf(togv, "(geometry \"pick\" { INST tlist { LIST { :edgeT } } geom { \n");
- GeomFSave(g, togv, "hinge output pipe (geometry pick...)");
- fprintf(togv, " } } )\n");
-
- fflush(togv);
- }
-
- void
- Inst(int n, float ang)
- {
- ComputeTransform(*(TT[n]), BaseT, ang);
- fprintf(togv,"(read geometry { define T%1d TLIST\n",n);
- fputtransform(togv, 1, (float*)(TT[n]), 0);
- fprintf(togv," } )\n");
- fflush(togv);
- }
-
- void
- Undo()
- {
- int i;
-
- for (i=0; i<MAXTHINGS && TT[i]!=NULL; ++i);
- if (i==MAXTHINGS || i<=1) return;
-
- --i;
- /* OOGLFree(TT[i]); */
- free(TT[i]);
- TT[i] = NULL;
- fprintf(togv,"(delete \"geom%1d\")\n", i);
- fflush(togv);
- }
-
- void
- Reset()
- {
- int i;
-
- fprintf(togv,"(progn\n");
- for (i=1; i<MAXTHINGS && TT[i]!=NULL; ++i) {
- /* OOGLFree(TT[i]); */
- free(TT[i]);
- TT[i] = NULL;
- fprintf(togv,"(delete \"geom%1d\")\n", i);
- }
- haveaxis = 0;
- ShowAxis();
- fprintf(togv,")\n");
- fflush(togv);
- }
-
- void
- ShowAxis()
- {
- Transform Ta, TaInv, R, Tloc, Tsize, Tnet;
- Point3 a, b, b1;
- float b1halflen, radius;
-
- if (haveaxis) {
-
- space_alignZ(¤tedge[0], ¤tedge[1], Tloc);
- HPt3TransPt3(Tloc, ¤tedge[1], &b1);
- TmInvert(Tloc, Tloc);
- b1halflen = .5 * Pt3Length(&b1);
-
- TmTranslate( Tsize, (float)0, (float)0, b1halflen );
- radius = .05 * b1halflen;
- CtmScale( Tsize, radius, radius, b1halflen );
-
- TmConcat(Tsize, Tloc, Tnet);
-
- fprintf(togv,"(read geometry { define edgeT TLIST\n");
- fputtransform(togv, 1, (float*)Tnet, 0);
- fprintf(togv," } )\n");
-
- } else {
-
- fprintf(togv,"(read geometry { define edgeT { LIST } })\n");
-
- }
-
- fflush(togv);
- }
-
- void space_translate_origin(Point *pt, Transform T)
- {
- switch(space) {
- case HYPERBOLIC:
- TmHypTranslateOrigin(T, pt);
- break;
- case SPHERICAL:
- TmSphTranslateOrigin(T, pt);
- break;
- default:
- case EUCLIDEAN: TmTranslateOrigin(T, pt); break;
- }
- }
-
- void HingeSpace(int s)
- {
- switch (s) {
- case HYPERBOLIC:
- space = HYPERBOLIC;
- fprintf(togv, "\
- (progn\n\
- (space hyperbolic)\n\
- (camera-reset allcams)\n\
- (merge-baseap appearance { +edge shading constant })\n\
- )\n");
- fflush(togv);
- break;
- case SPHERICAL:
- space = SPHERICAL;
- fprintf(togv, "\
- (progn\n\
- (space spherical)\n\
- (camera-reset allcams)\n\
- (merge-baseap appearance { +edge shading constant })\n\
- )\n");
- fflush(togv);
- break;
- case EUCLIDEAN:
- default:
- space = EUCLIDEAN;
- fprintf(togv, "\
- (progn\n\
- (space euclidean)\n\
- (merge-baseap appearance { +edge shading flat })\n\
- )\n");
- fflush(togv);
- break;
- }
- }
-
- /*
- returns T = transform taking a to 0 and b to
- a point on the +Z axis
- */
- static void space_alignZ(Point *a, Point *b, Transform T)
- {
- Transform Ta, R;
- Point b1;
-
- /* Ta = transform taking a to origin */
- space_translate_origin(a, Ta);
- TmInvert(Ta,Ta);
-
- /* b1 = image of b under Ta */
- HPt3Transform(Ta, b, &b1);
-
- /* R = transform rotating b1 to +Z axis */
- TmRotateTowardZ(R, &b1);
-
- /* answer T is Ta * R */
- TmConcat(Ta, R, T);
- }
-